package us.esme.lib

/*
 * Copyright 2008 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by apwant to grabplicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 */


import net.liftweb._
import http._
import js._
import JE._
import JsCmds._
import SHtml._
import util._
import Helpers._
import sitemap._
import mapper._
import Loc._

import us.esme._
import model._

import scala.xml.{NodeSeq, Text, Elem}

import java.util.logging._

object UserView {
  def loggedIn_? = User.loggedIn_?
  
  val ifIsLoggedIn = If(loggedIn_? _, "You must be logged in")

  val menuItems =
  Menu(Loc("userView", List("user_view", "index"), "View User",
           Snippet("following_button", followingButton _),
           Snippet("messages", messagesForUser _),
           Snippet("sent_messages", messagesUserSent _),
           Snippet("user_name", userName _),
           Snippet("following", doFollowing _),
           Snippet("followers", doFollowers _),
           Hidden)) ::
  Menu(Loc("view tag", List("user_view", "tag"), "View Tag",
           Snippet("tag_name", tagName _),
           Snippet("tag", doTag _),
           Hidden)) ::
  Menu(Loc("search", List("user_view", "search"), "Search",
           Snippet("search_term", searchTerm _),
           Snippet("search", doSearch _),
           Hidden)) ::
  Menu(Loc("allUsers", List("user_view", "all"), "All Users",
           Snippet("all_users", listAllUsers _))) ::
  Menu(Loc("conversation", List("user_view", "index"), "View User",
           Snippet("conversation", doConversation _), Hidden)) ::
  Nil

  def putMessages(in: List[Message]): NodeSeq =
  Script(OnLoad(JsFunc("put_messages_at", messageDest,
                JsArray(in.map(_.asJs) :_*)).cmd))

  def doConversation(ignore: NodeSeq): NodeSeq = 
  {
    val cid = S.param("cid").map(toLong).openOr(-1L)

    putMessages(Message.findAndPrime(By(Message.conversation, cid),
                                     OrderBy(Message.id, Ascending)))
  }

  def doFollow(in: NodeSeq, f: User => List[User]): NodeSeq =
  referencedUser.is.toList.flatMap(u =>
    f(u).flatMap(f => bind("follow", in,
      "link" -> <a href={"/user/"+urlEncode(f.nickname.is)}>{f.niceName}</a>)))

   def doFollowers(in: NodeSeq): NodeSeq = doFollow(in, _.followers)


  def doFollowing(in: NodeSeq): NodeSeq = doFollow(in, _.following)
  
 

  def userName(in: NodeSeq): NodeSeq =
  referencedUser.is.toList.map(u => Text(u.niceName))

  def listAllUsers(html: NodeSeq): NodeSeq = 
  User.findAll(OrderBy(User.nickname, Ascending)).
  flatMap(u => bind("user", html,
                    "link" -> <a href={"/user/"+urlEncode(u.nickname.is)}>{u.niceName}</a>,
                    "firstname" -> u.firstName, "lastname" -> u.lastName))

  def followingButton(html: NodeSeq): NodeSeq = {
    val spanId = S.attr("span_id") openOr "none"
    val user: Can[User] = referencedUser

    def updateFollow: JsCmd = SetHtml(spanId, doButton)

    def doButton: NodeSeq = {
      (User.currentUser, user) match {
        case (Full(u), Full(user)) if u != user =>
          if (u.following_?(user))
          ajaxButton("Unfollow", () => {u.unfollow(user); updateFollow})
          else ajaxButton("Follow", () => {u.follow(user); updateFollow})

        case _ => NodeSeq.Empty
      }
    }

    doButton
  }

  def messagesForUser(html: NodeSeq): NodeSeq =
  referencedUser.is match {
  case Full(user) =>
    putMessages(Mailbox.mostRecentMessagesFor(user.id,
                                            50).map(_._1))
  case _ => NodeSeq.Empty
  }

  def messagesUserSent(html: NodeSeq): NodeSeq =
  referencedUser.is match {
    case Full(user) => 
      putMessages(Message.findAll(By(Message.author,user),
                              MaxRows(50), OrderBy(Message.id, Descending)))
  case _ => NodeSeq.Empty
  }

  def searchTerm(ignore: NodeSeq): NodeSeq = Text(theSearchTerm)

  object theSearchTerm extends RequestVar(S.param("term") openOr "")

  def curUserFollowing: List[User] = 
  for (u <- User.currentUser.toList; f <- u.followers) yield f

  def messageDest = Str(S.attr("destination") openOr "Nowhere")

  def doSearch(ignore: NodeSeq): NodeSeq =
  putMessages(Message.search(theSearchTerm,
                             curUserFollowing,
                             50))

  object theTagName extends RequestVar((S.param("tag") openOr "").trim)

  def tagName(ignore: NodeSeq): NodeSeq = Text(theTagName)

  def messagesForTag: List[Message] =
  for (tag <- Tag.find(By(Tag.name, theTagName)).toList;
       m <- tag.findMessages()) yield m

  def doTag(ignore: NodeSeq): NodeSeq = 
  putMessages(messagesForTag)

  object referencedUser extends
  RequestVar(for (uid <- S.param("uid");
                  user <- User.findFromWeb(uid)) yield user)
}
